﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Input;

using BackgroundTest.LogicInterface;

namespace BackgroundTest.BasicAbstracts
{

    /************************************************************************/
    /* Class name: MouseTrack                                               */
    /* Function: Track the motion of the mouse, and provide available data  */
    /*           for relative classes.                                      */
    /************************************************************************/

    public class MouseTrack
    {
        private static MouseTrack instance;

        public static MouseTrack Instance
        {
            get
            {
                if (null == instance)
                {
                    instance = new MouseTrack();
                }
                return instance;
            }
        }

        // The value that remembers the absolute position of the mouse.
        private VectorScreen position;

        public VectorScreen Position
        {
            //set { position = value; }
            get { return position; }
        }

        // The value that remembers the difference of position between the 
        // current frame and the last one.
        private VectorScreen mouseMove;

        public VectorScreen MouseMovement
        {
            //set { mouseMove = value; }
            get { return mouseMove; }
        }

        // The value that remembers the logic position of the mouse.
        //static private VectorMap mapPosition;
        
        //static public VectorMap MapPosition
        //{
            //set { mapPosition = value; }
            //get { return mapPosition; }
        //}

        private MouseTrack()
        {
            position = new VectorScreen(Mouse.GetState().X, Mouse.GetState().Y);
            mouseMove = new VectorScreen(0, 0);
        }

        public void UpdateMousePosition()
        {
            mouseMove.x = Mouse.GetState().X - position.x;
            mouseMove.y = Mouse.GetState().Y - position.y;
            position.x = Mouse.GetState().X;
            position.y = Mouse.GetState().Y;
        }
    }

    /************************************************************************/
    /* Class name: KeyboardSense                                            */
    /* Function: Sense the behavior of keyboard.                            */
    /************************************************************************/

    public class KeyboardSense
    {
        private static KeyboardSense instance;

        public static KeyboardSense Instance
        {
            get
            {
                if (null == instance)
                {
                    instance = new KeyboardSense();
                }
                return instance;
            }
        }

        // The key pressed on the last frame, 0~25:a~z, 26~29:up,left,down,right
        protected Keys[] lastpressed;

        // The key pressed on this frame
        protected Keys[] nowpressed;

        /************************************************************************/
        /* Method name: Construction Function                                   */
        /************************************************************************/
        private KeyboardSense ()
        {
            lastpressed = Keyboard.GetState().GetPressedKeys();
            nowpressed = Keyboard.GetState().GetPressedKeys();
        }

        /// <summary>
        /// Bind the class with Lua.
        /// </summary>
        public void BindWithLua()
        {
            BackgroundTest.BackGroundTest.Console.WriteLine("@Keyboard>  Registering...");
            LuaFramework.Instance.registerLuaFunctions(instance);
            BackgroundTest.BackGroundTest.Console.WriteLine("@Keyboard>  Register finished.");
        }

        /************************************************************************/
        /* Method name: IfKeyDown                                               */
        /* Parameters: Keys: The testing key's name.                            */
        /************************************************************************/
        public void Update()
        {
            lastpressed = nowpressed;
            nowpressed = Keyboard.GetState().GetPressedKeys();
        }

        /// <summary>
        /// Changes an integer into the enumerator type Keys
        /// </summary>
        /// <param name="_number">The number of the key</param>
        /// <returns>The Keys' type</returns>
        public Keys IntToKey(int _number)
        {
            return (Keys)Enum.ToObject(typeof(Keys), _number);
        }

        /************************************************************************/
        /* Method name: IsKeyTriggerUp                                          */
        /* Parameters: Keys: Return whether the key is last pressed and now     */
        /*                   released.                                          */
        /************************************************************************/
        public bool IsKeyTriggerUp (Keys _key)
        {
            return (lastpressed.Contains(_key) && (!nowpressed.Contains(_key)));
        }

        /// <summary>
        /// Returns whether the key presented by the number is last pressed and now released
        /// </summary>
        /// <param name="_number">The number of the key</param>
        /// <returns>whether the key is triggering up</returns>
        public bool IsKeyTriggerUpInt(int _number)
        {
            return (lastpressed.Contains(IntToKey(_number)) && (!nowpressed.Contains(IntToKey(_number))));
        }

        /************************************************************************/
        /* Method name: IsKeyTriggerDown                                        */
        /* Parameters: Keys: Return whether the key is last released and now    */
        /*                   pressed.                                           */
        /************************************************************************/
        public bool IsKeyTriggerDown(Keys key)
        {
            return ( (!lastpressed.Contains(key)) && nowpressed.Contains(key));
        }

        /// <summary>
        /// Returns whether the key is last released and now pressed
        /// </summary>
        /// <param name="_number">The number of the key</param>
        /// <returns>whether the key is triggering down</returns>
        [AttrLuaFunc("IsKeyDown", "Returns whether the key is last released and now pressed",
            "The number of the key")]
        public bool IsKeyTriggerDownInt(int _number)
        {
            return (!lastpressed.Contains(IntToKey(_number)) && (nowpressed.Contains(IntToKey(_number))));
        }

        /************************************************************************/
        /* Method name: IfKeyDown                                               */
        /* Parameters: Keys: The testing key's name.                            */
        /************************************************************************/
        public bool IsKeyDown(Keys _key)
        {
            return Keyboard.GetState().IsKeyDown(_key);
        }
    }
}
